/*
 * Shell.c
 *
 *  Created on: 2 mars 2012
 *      Author: Jeff
 */

#include <Arduino.h>
#include "Shell.hpp"
#include "config.h"
#include "Buffer.hpp"
#include "Parsing.hpp"

#include "Instances.hpp"

const Buffer shellbuffer;
const Parser shellparser((Buffer *)&shellbuffer);
const CommandHandler shellcommandHandler;
const ArgumentHandler shellargumentHandler;

Shell::Shell() {
	buffer = (Buffer*)&shellbuffer;
	parser = (Parser*)&shellparser;

	argHdl = (ArgumentHandler*)&shellargumentHandler;
	argHdl->registerAll((struct Argument *)configArgumentTypes, SHELL_ARGUMENT_COUNT);

	cmdHdl = (CommandHandler*)&shellcommandHandler;
	cmdHdl->registerAll(configCommandRefList, SHELL_COMMAND_COUNT);
	cmdHdl->registerArguments(argHdl);
}

void Shell::setup() {
	OUTPUT_PRINT("SHELL//");
}

const char * shellMessageOK = "OK";
const char * shellMessageSyntaxError = "Syntax Error !";
const char * shellMessageWrongArguments = "Wrong number of arguments !";
const char * shellMessageCmdNotFound = "Command not found !";

void Shell::loop() {
	buffer->zero();
	parser->parseReset();
	buffer->read();

#ifdef SHELL_ECHO
	OUTPUT_WRITE((byte *)buffer->bufferSpace,buffer->bufferIndex);
	OUTPUT_PRINT('\n');
#endif

#ifdef SHELL_DEBUG
	buffer->display();
#endif
	parser->parseLine();
#ifdef SHELL_DEBUG
	parser->display();
#endif


	if ((parser->parsingStatus != SHELL_PARSINGSTATUS_FINISHED)) {
		OUTPUT_PRINTLN(shellMessageSyntaxError);
		return;
	}

	currentCmd = cmdHdl->matchCommand(parser->parsedName);
#ifdef SHELL_DEBUG
	OUTPUT_PRINT("currentCmd=");
	OUTPUT_PRINTLN(currentCmd);
#endif

	if (currentCmd != 255) {
#ifdef SHELL_DEBUG
			OUTPUT_PRINT(cmdHdl->commands[currentCmd].argCount);
			OUTPUT_PRINT("?=");
			OUTPUT_PRINTLN(parser->parsedArgCount);
#endif
		if (pgm_read_byte(&(cmdHdl->commands[currentCmd]->argCount)) != parser->parsedArgCount) {
			OUTPUT_PRINTLN(shellMessageWrongArguments);
			return;
		}
		if (!cmdHdl->parseCommandEnvironment(currentCmd, parser->parsedArguments, &currentEnv)) {
			OUTPUT_PRINTLN(shellMessageSyntaxError);
			return;
		}
		cmdHdl->executeCommand(currentCmd, &currentEnv);
		OUTPUT_PRINTLN(shellMessageOK);
		return;
	} else {
		OUTPUT_PRINTLN(shellMessageCmdNotFound);
		return;
	}
}
